﻿// 2025/10/14: 首个版本
// 2025/10/15: 颜色修正

using System;
using System.Threading.Tasks;
using Avalonia.Threading;
using ASEva;
using ASEva.UIAvalonia;
using CommunityToolkit.Mvvm.ComponentModel;
using Avalonia.Media;
using CommunityToolkit.Mvvm.Input;

namespace CommonSource
{
    partial class TaskBanner : DialogPanel
    {
        public TaskBanner() // For designer
        {
            InitializeComponent();
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
        }

        public TaskBanner(String title, bool withCheckDetails = false)
        {
            InitializeComponent();
            SetFixMode(700, 100, false);
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());

            model = new Model(title, withCheckDetails);
            DataContext = model;
        }

        public override void OnClosing()
        {
            BoolResult = model.CheckDetails;
        }

        public async Task RunTask(WorkflowRunTaskCallback callback)
        {
            if (running) return;
            else running = true;

            model.Callback = callback;

            loopTimer = new DispatcherTimer();
            loopTimer.Interval = TimeSpan.FromSeconds(0.1);
            loopTimer.Tick += delegate
            {
                if (looping) return;
                looping = true;

                model.TaskState = callback.GetTaskState();
                model.Description = callback.GetTaskStateDescription() ?? "";
                if (model.TaskState != TaskState.Failed)
                {
                    model.Percent = Math.Max(0.0, Math.Min(100.0, callback.GetTaskProgress()));
                }

                if (model.TaskState == TaskState.Failed || model.TaskState == TaskState.Finished)
                {
                    model.CanCancel = false;
                    loopTimer.Stop();
                    loopTimer = null;

                    closeTimer = new DispatcherTimer();
                    closeTimer.Interval = TimeSpan.FromSeconds(2);
                    closeTimer.Tick += delegate
                    {
                        closeTimer.Stop();
                        closeTimer = null;
                        Close();
                    };
                    closeTimer.Start();
                }

                looping = false;
            };
            loopTimer.Start();

            await App.RunDialog(this);
        }

        private partial class Model(String _title, bool withCheckDetails) : ObservableObject
        {
            public WorkflowRunTaskCallback Callback { get; set; }

            [ObservableProperty]
            private string title = _title;

            [ObservableProperty]
            private string description = "";

            [ObservableProperty]
            [NotifyPropertyChangedFor(nameof(PercentText))]
            private double percent = 0.0;

            public String PercentText => Percent.ToString("F1") + "%";

            [ObservableProperty]
            private bool showCheckDetails = withCheckDetails;

            [ObservableProperty]
            private bool checkDetails = false;

            [ObservableProperty]
            [NotifyPropertyChangedFor(nameof(TaskStateColor))]
            private TaskState taskState = TaskState.Unknown;

            public IBrush TaskStateColor => TaskState switch
            {
                TaskState.Progressing => App.DarkTheme ? Brushes.LightGray : Brushes.Black,
                TaskState.Failed => App.DarkTheme ? Brushes.Tomato : Brushes.Red,
                TaskState.Finished => App.DarkTheme ? Brushes.PaleGreen : Brushes.Green,
                _ => Brushes.Gray,
            };

            [ObservableProperty]
            private bool canCancel = true;

            [RelayCommand]
            private void Cancel()
            {
                CanCancel = false;
                Callback?.CancelTask();
            }
        }

        private Model model;
        private DispatcherTimer loopTimer, closeTimer;
        private bool running = false;
        private bool looping = false;

        private LanguageSwitch language;
    }
}